﻿using Furion;
using Furion.Logging;
using NetTaste;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using OnWork.DataCenter.BLL.DataCenter;
using OnWork.DataCenter.BLL.Standard.Conver;
using OnWork.DataCenter.BLL.Standard.Dto;
using OnWork.DataCenter.DAL;
using OnWork.DataCenter.DAL.DataCenter;
using OnWork.DataCenter.Utils;
using OnWork.DataCenter.Utils.Caches;
using SqlSugar;
using System.Data;
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
using static OnWork.DataCenter.Utils.StringFormat;

namespace OnWork.DataCenter.BLL.Standard
{
    /// <summary>
    /// 标准转换
    /// </summary>
    public class StandardConvert
    {
        /// <summary>
        /// 解析json结果
        /// </summary>
        /// <param name="config"></param>
        /// <param name="jsonStr">json字符串</param>
        /// <returns></returns>
        public static DataTable JsonToDataTable(string jsonStr, JsonToDataTableConfig config)
        {
            IJsonToDataTableConver conert;

            switch (config.Type)
            {
                case JsonToDataTableType.Default: //默认公式解析
                    conert = new JsonToDataTableDefaultConver();
                    break;

                case JsonToDataTableType.DFS: //大佛寺解析
                    conert = new JsonToDataTableDFSConver();
                    break;

                case JsonToDataTableType.GJW: //郭家湾解析
                    conert = new JsonToDataTableGJWConver();
                    break;

                case JsonToDataTableType.YJG: //闫家沟
                    conert = new JsonToDataTableYJGConver();
                    break;

                default:
                    conert = new JsonToDataTableDefaultConver();
                    break;
            }

            return conert.Conver(jsonStr, config);
        }

        /// <summary>
        /// 解析json结果缓存到变量中
        /// </summary>
        /// <param name="config"></param>
        /// <param name="jsonStr">json字符串</param>
        /// <returns></returns>
        public static Dictionary<string, string> JsonToVariables(string jsonStr, JsonToVariablesConfig config)
        {
            var o = JObject.Parse(jsonStr);
            Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();

            foreach (var v in config.Variables)
            {
                string token = v.VariableSelectToken;
                var result = (string)o.SelectToken(token);
                if (result.IsNotEmptyOnWork())
                {
                    //不为空的话则赋值到遍历
                    VariablesCache.Set(v.VariableName, result);
                    keyValuePairs.Add(v.VariableName, result);
                }
            }
            return keyValuePairs;
        }

        /// <summary>
        /// DateTable转字符串
        /// </summary>
        /// <param name="dataTable"></param>
        /// <returns></returns>
        public static DataTable JsonToDataTable(string json)
        {
            return JsonConvert.DeserializeObject<DataTable>(json);
        }

        /// <summary>
        /// Json转MQTT
        /// </summary>
        /// <param name="json"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static void JsonToMqtt(string json, JsonToMqttConfig config)
        {
            var mqtt = DBManger.DataCenter.Queryable<DSMqtt>().Where(x => x.ID == config.MqttID).First();
            //获取MQTT对象
            if (mqtt != null)
            {
                //发送MQTT消息
                HostedService.MqttHostedService.MqttPublish(mqtt, config.Topic, json);
            }
        }

        /// <summary>
        /// DateTable转字符串
        /// </summary>
        /// <param name="dataTable"></param>
        /// <returns></returns>
        public static string DataTableToString(DataTable dataTable)
        {
            StringBuilder stringBuilder = new StringBuilder();
            //列名
            var colNum = dataTable.Columns.Count;
            for (int i = 0; i < colNum; i++)
            {
                stringBuilder.Append(dataTable.Columns[i].ColumnName);
                stringBuilder.Append("  ");
            }
            stringBuilder.AppendLine();

            foreach (DataRow row in dataTable.Rows)
            {
                for (int i = 0; i < colNum; i++)
                {
                    stringBuilder.Append(row[i]);
                    stringBuilder.Append("  ");
                }
                stringBuilder.AppendLine();
            }
            return stringBuilder.ToString();
        }

        /// <summary>
        /// DateTable转字符串
        /// </summary>
        /// <param name="dataTable"></param>
        /// <returns></returns>
        public static string DataTableToJson(DataTable dataTable)
        {
            string JsonString = string.Empty;
            JsonString = JsonConvert.SerializeObject(dataTable, Formatting.Indented);
            return JsonString;
        }

        /// <summary>
        /// Http转JSOn
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static string HttpToJson(HttpToJsonConfig config)
        {
            var httpClientFactory = App.GetService<IHttpClientFactory>();
            var httpResponseMessage = config.Http.Request(httpClientFactory.CreateClient());
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                var contentheaders = httpResponseMessage.Content.Headers; //获取响应内容头
                var stream = httpResponseMessage.Content.ReadAsStream();//获取内容字节对象
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                stream.Seek(0, SeekOrigin.Begin); //设置当前流的位置为开始位置
                foreach (var item in contentheaders)
                {
                    var key = item.Key;

                    if (key == "Content-Encoding")
                    {
                        if (item.Value.Contains("gzip", true))
                        {
                            bytes = bytes.GZipDecompressOnWork();//解压缩数据
                        }
                    }
                }
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                var val = System.Text.Encoding.GetEncoding("UTF-8").GetString(bytes);
                return val;
            }
            return JsonHelper.SerializeFormat(httpResponseMessage);
        }

        /// <summary>
        /// Http转JSOn
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static async Task<string> HttpToJsonAsync(HttpToJsonConfig config)
        {
            var httpClientFactory = App.GetService<IHttpClientFactory>();
            var httpResponseMessage = await config.Http.RequestAsync(httpClientFactory.CreateClient());
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                var contentheaders = httpResponseMessage.Content.Headers; //获取响应内容头
                var bytes = await httpResponseMessage.Content.ReadAsByteArrayAsync();//获取内容字节对象
                foreach (var item in contentheaders)
                {
                    var key = item.Key;

                    if (key == "Content-Encoding")
                    {
                        if (item.Value.Contains("gzip", true))
                        {
                            bytes = bytes.GZipDecompressOnWork();//解压缩数据
                        }
                    }
                }
                Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                var val = System.Text.Encoding.GetEncoding("UTF-8").GetString(bytes);
                return val;
            }
            return JsonHelper.SerializeFormat(httpResponseMessage);
        }

        public static string ExeToExe(ExeToExeConfig config) {
            //程序的参数
            ProcessStartInfo Info = new ProcessStartInfo()
            {
                UseShellExecute = false,
                FileName = config.FileName, //执行程序
                Arguments = config.Arguments, //执行参数
                RedirectStandardOutput = true, //输出调转
                CreateNoWindow = !config.IsShowWindowsForm,//不可见进程
                                                           //WindowStyle = ProcessWindowStyle.Hidden
            };

            //使用管理员启动
            if (config.IsRunAsAdmin)
            {
                Info.Verb = "runas";
            }

            //指定启动路径 解决出错问题

            var dirName = config.WorkingDirectory;

            //如果没配置则默认获取配置exe的路径
            if (dirName.IsEmptyOnWork())
            {
                FileInfo fileInfo = new FileInfo(config.FileName);
                dirName = fileInfo.DirectoryName;
            }

            if (dirName.IsNotEmptyOnWork())
            {
                Info.WorkingDirectory = dirName;
            }

            Process process = new Process();
            //obj.State = "启动中";
            //obj.OutputAppend("启动中");
            process.StartInfo = Info;
            //process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
            //{
            //    // Prepend line numbers to each line of the output.
            //    if (!string.IsNullOrEmpty(e.Data))
            //    {
            //        //添加日志
            //        obj.OutputAppend(e.Data);
            //    }
            //});  //输出接收
            //process.EnableRaisingEvents = true; //退出时引发中止命令
            //process.Exited += new EventHandler((sender, e) =>
            //{
            //    //移除
            //    dicProcess.TryRemove(obj, out var pro);
            //    obj.State = "已停止";
            //    obj.OutputAppend("已停止");
            //});
            var isok = process.Start();
            if (isok)
            {
                //obj.State = "运行中";
                //obj.OutputAppend("运行中");
                //dicProcess[obj] = process;
                //obj.ProcessName = process.ProcessName;
                //obj.MainWindowTitle = process.MainWindowTitle;

                process.BeginOutputReadLine();

                return "启动完成";
            }
            else
            {
                // obj.State = "启动失败";
                return "启动失败";
            }

        }

        /// <summary>
        /// Exe执行
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        public static async Task<string> ExeToExeAsync(ExeToExeConfig config)
        {
            await Task.Run(() =>
            {
                ExeToExe(config);
            });

            return "";
        }

        /// <summary>
        /// 数据库查询到DataTable
        /// </summary>
        /// <param name="config"></param>
        /// <param name="jsonStr">json字符串</param>
        /// <returns></returns>
        public static string DataTableToJsonWithConfig(DataTable input, DataTableToJsonConfig config)
        {
            DataTable dataTable = new DataTable();

            //创建列
            foreach (var item in config.Cols)
            {
                DataColumn dc = new DataColumn()
                {
                    ColumnName = item.ColName,
                    DataType = typeof(String),
                };
                dataTable.Columns.Add(dc);
            }

            //遍历输入列
            foreach (DataRow row in input.Rows)
            {
                //创建行
                DataRow dr = dataTable.NewRow();

                for (int i = 0; i < config.Cols.Count; i++)
                {
                    //获取值
                    string token = config.Cols[i].ColSelectToken;
                    //使用相关配置 如果使用$则使用公式
                    if (token.StartsWith("$"))
                    {
                        dr[i] = token.Formula();
                    }
                    else
                    {
                        dr[i] = row[token];
                    }
                }
                dataTable.Rows.Add(dr);
            }

            string jsonData = DataTableToJson(dataTable);

            SafeMap<object> map = new SafeMap<object>();
            map["timestamp"] = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString();
            map["data"] = jsonData;
            return ReplacePlaceholder(config.Template, map);
        }

        /// <summary>
        /// dataTable插入数据库
        /// </summary>
        /// <param name="input"></param>
        /// <param name="config"></param>
        public static int DataTableToDataBase(DataTable input, DataTableToDBConfig config)
        {
            var dt = new DataTable();
            dt.TableName = config.DBTable; //设置表名

            //创建列
            foreach (var item in config.DBCols)
            {
                //配置不为空才添加
                if (item.ColSelectToken.IsNotEmptyOnWork())
                {
                    DataColumn dc = new DataColumn()
                    {
                        ColumnName = item.ColName,
                    };

                    //查询原来表格的列
                    var index = input.Columns.IndexOf(item.ColSelectToken);
                    if (index > -1)
                    {
                        dc.DataType = input.Columns[index].DataType; //配置数据类型
                    }
                    else
                    {
                        //数据类型
                        switch (item.ColType)
                        {
                            case DataType.String:
                                dc.DataType = typeof(string);
                                break;

                            case DataType.Int32:
                                dc.DataType = typeof(int);
                                break;

                            case DataType.Boolean:
                                dc.DataType = typeof(bool);
                                break;

                            case DataType.DateTime:
                                dc.DataType = typeof(DateTime);
                                break;

                            case DataType.Decimal:
                                dc.DataType = typeof(decimal);
                                break;

                            default:
                                dc.DataType = typeof(string);
                                break;
                        }
                    }
                    dt.Columns.Add(dc);
                }
            }

            foreach (DataRow row in input.Rows)
            {
                var addRow = dt.NewRow();

                foreach (var item in config.DBCols)
                {
                    try
                    {
                        //配置不为空才添加
                        if (item.ColSelectToken.IsNotEmptyOnWork())
                        {
                            //使用相关配置
                            if (item.ColSelectToken.StartsWith("$"))
                            {
                                if (item.ColSelectToken == "${DateTime.Now}")
                                {
                                    addRow[item.ColName] = DateTime.Now;
                                }
                                else
                                {
                                    //行转数据
                                    Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
                                    foreach (var colitem in config.DBCols)
                                    {
                                        if (item.ColSelectToken.Contains(colitem.ColName))
                                        {
                                            keyValuePairs.Add(colitem.ColName, row[colitem.ColName]);
                                        }
                                    }

                                    var result = item.ColSelectToken.Formula(null, keyValuePairs);//将一整行的数据传入
                                    addRow[item.ColName] = result;
                                }
                            }
                            else
                            {
                                var ss1 = dt.Columns[item.ColName].DataType;
                                addRow[item.ColName] = row[item.ColSelectToken];
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        var s = e.ToString();
                        //throw;
                    }
                }
                //addRow["id"] = 0;
                //addRow["price"] = 1;
                //addRow["Name"] = "a";
                dt.Rows.Add(addRow);//添加数据
            }

            //DataTable插入数据
            //创建数据库对象
            //获取SqlSugar 对象
            string key = ""; //缓存主键
            if (config.DBID > 0)
            {
                key = config.DBID.ToString();
            }
            else
            {
                key = config.DBConn;
            }

            SqlSugarScope db = SqlSugarCache.GetOrCreate(config.DBType, config.DBConn, key);

            if (config.ConfigType == DataTableToDBConfigType.InsertOnly) //仅插入
            {
                //db.Fastest<System.Data.DataTable>().AS(config.DBTable).BulkCopy(dt);
                List<Dictionary<string, object>> dc = db.Utilities.DataTableToDictionaryList(dt);//5.0.23版本支持
                return db.Insertable(dc).AS(config.DBTable).ExecuteCommand();// ExecuteReturnIdentity();
            }
            else if (config.ConfigType == DataTableToDBConfigType.DeleteInsert) //删除并插入
            {
                db.DbMaintenance.TruncateTable(config.DBTable);
                List<Dictionary<string, object>> dc = db.Utilities.DataTableToDictionaryList(dt);//5.0.23版本支持
                return db.Insertable(dc).AS(config.DBTable).ExecuteCommand();// ExecuteReturnIdentity();
            }
            else if (config.ConfigType == DataTableToDBConfigType.UpdateInsert) //更新插入
            {
                var pks = config.DBCols.Where(x => x.IsPK == true).Select(x => x.ColName).ToList(); //主键字段
                if (pks != null && pks.Count() > 0)
                {
                    var x = db.Storageable(dt).WhereColumns(pks).ToStorage();//id作为主键
                    int icount = x.AsInsertable.ExecuteCommand();//如果是自增要添加IgnoreColumns
                    int ucount = x.AsUpdateable.ExecuteCommand();
                    return icount + ucount;
                }
            }
            else if (config.ConfigType == DataTableToDBConfigType.DeleteByPK) //仅删除(依据主键)
            {
                var pks = config.DBCols.Where(x => x.IsPK == true).Select(x => x.ColName).ToList(); //主键字段
                if (pks != null && pks.Count() > 0)
                {
                    var x = db.Storageable(dt).WhereColumns(pks).ToStorage();//id作为主键
                    return x.AsDeleteable.ExecuteCommand(); //删除
                }
            }
            return 0;
        }

        /// <summary>
        /// 数据库查询到DataTable
        /// </summary>
        /// <param name="config"></param>
        /// <param name="jsonStr">json字符串</param>
        /// <returns></returns>
        public static DataTable DataBaseToDataTable(DBToDataTableConfig config)
        {
            //DataTable插入数据
            //创建数据库对象
            string key; //缓存主键
            if (config.DBID > 0) { key = config.DBID.ToString(); } else { key = config.DBConn; }
            SqlSugarScope db = SqlSugarCache.GetOrCreate(config.DBType, config.DBConn, key);
            //无参数
            var dataTable = db.CopyNew().Ado.GetDataTable(config.SQL);
            return dataTable;
        }

        /// <summary>
        /// 数据库查询到DataTable
        /// </summary>
        /// <param name="config"></param>
        /// <param name="jsonStr">json字符串</param>
        /// <returns></returns>
        public static async Task<DataTable> DataBaseToDataTableAsync(DBToDataTableConfig config)
        {
            //DataTable插入数据
            //创建数据库对象
            string key = ""; //缓存主键
            if (config.DBID > 0) { key = config.DBID.ToString(); } else { key = config.DBConn; }
            SqlSugarScope db = SqlSugarCache.GetOrCreate(config.DBType, config.DBConn, key);
            //无参数
            var dataTable = await db.Ado.GetDataTableAsync(config.SQL);
            return dataTable;
        }

        /// <summary>
        /// 从流程配置进行解决
        /// </summary>
        /// <param name="trees"></param>
        public static void ProcessTreeStandards(List<DataStandardTreeDto> trees, object data = null)
        {
            foreach (var item in trees)
            {
                ProcessTreeStandard(item, data); //跟节点不需要执行
            }
        }

        /// <summary>
        /// 执行标准功能
        /// </summary>
        /// <param name="tree">标准节点</param>
        /// <param name="data">往下执行的数据对象</param>
        /// <returns></returns>
        private static bool ProcessTreeStandard(DataStandardTreeDto tree, object data)
        {
            //获当前节点的ID
            var stalls = DataStandardBLL.GetALLStandardsCache(); //获取查询的结果
            DataStandard dataStandard = stalls.Where(x => x.ID == tree.ID).FirstOrDefault();

            if (dataStandard != null)
            {
                var result = ProcessStandard(dataStandard, data);
                if (result.IsSuccess)
                {
                    foreach (var child in tree.Childs)
                    {
                        ProcessTreeStandard(child, result.Result);
                    }
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// 处理数据标准
        /// </summary>
        /// <param name="dataStandard"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static ProcessStandardResultDto ProcessStandard(DataStandard dataStandard, object data)
        {
            try
            {
                object tmpData = data;
                //json转DataTable
                if (dataStandard.DataType == DataStandardType.Json && dataStandard.OutType == DataStandardType.DataTable)
                {
                    var result = StandardConvert.JsonToDataTable(tmpData as string, JsonConvert.DeserializeObject<JsonToDataTableConfig>(dataStandard.StandardConfig));
                    if (result != null)
                    {
                        return new ProcessStandardResultDto(true, dataStandard.OutType, result);
                    }
                }
                //DataTable转数据库
                else if (dataStandard.DataType == DataStandardType.DataTable && dataStandard.OutType == DataStandardType.DataBase)
                {
                    StandardConvert.DataTableToDataBase(tmpData as DataTable, JsonConvert.DeserializeObject<DataTableToDBConfig>(dataStandard.StandardConfig));
                    return new ProcessStandardResultDto(true, dataStandard.OutType, null);
                }
                //数据库转表格
                else if (dataStandard.DataType == DataStandardType.DataBase && dataStandard.OutType == DataStandardType.DataTable)
                {
                    var tb = StandardConvert.DataBaseToDataTable(JsonConvert.DeserializeObject<DBToDataTableConfig>(dataStandard.StandardConfig));
                    if (tb != null)
                    {
                        return new ProcessStandardResultDto(true, dataStandard.OutType, tb);
                    }
                }
                //表格转JSON
                else if (dataStandard.DataType == DataStandardType.DataTable && dataStandard.OutType == DataStandardType.Json)
                {
                    var result = StandardConvert.DataTableToJsonWithConfig(tmpData as DataTable, JsonConvert.DeserializeObject<DataTableToJsonConfig>(dataStandard.StandardConfig));
                    if (result != null)
                    {
                        return new ProcessStandardResultDto(true, dataStandard.OutType, result);
                    }
                }
                //json转Mqtt
                else if (dataStandard.DataType == DataStandardType.Json && dataStandard.OutType == DataStandardType.Mqtt)
                {
                    var config = JsonConvert.DeserializeObject<JsonToMqttConfig>(dataStandard.StandardConfig);
                    StandardConvert.JsonToMqtt(tmpData as string, config);
                    return new ProcessStandardResultDto(true, dataStandard.OutType, null);
                }
                //json转变量
                else if (dataStandard.DataType == DataStandardType.Json && dataStandard.OutType == DataStandardType.Variables)
                {
                    var config = JsonConvert.DeserializeObject<JsonToVariablesConfig>(dataStandard.StandardConfig);
                    StandardConvert.JsonToVariables(tmpData as string, config);
                    return new ProcessStandardResultDto(true, dataStandard.OutType, null);
                }
                //Http转JSON
                else if (dataStandard.DataType == DataStandardType.Http && dataStandard.OutType == DataStandardType.Json)
                {
                    var config = JsonConvert.DeserializeObject<HttpToJsonConfig>(dataStandard.StandardConfig);
                    var result = StandardConvert.HttpToJson(config);
                    if (result != null)
                    {
                        return new ProcessStandardResultDto(true, dataStandard.OutType, result);
                    }
                }
                else if (dataStandard.DataType == DataStandardType.Exe && dataStandard.OutType == DataStandardType.Exe) //执行exe
                {
                    var config = JsonConvert.DeserializeObject<ExeToExeConfig>(dataStandard.StandardConfig);
                    var re = StandardConvert.ExeToExe(config);
                    //Result = $"已经执行{config.FileName}程序!";
                }
                return new ProcessStandardResultDto(false, dataStandard.OutType, data); ;
            }
            catch (Exception ex)
            {
                Log.Error(ex.ToString());
                return new ProcessStandardResultDto(false, dataStandard.OutType, data); ;
                //throw;
            }
        }

        /// <summary>
        /// 按照配置的标准处理流程
        /// </summary>
        /// <param name="dataStandards">配置的处理流程</param>
        /// <param name="content">输入内容</param>
        /// <returns></returns>
        public static void ProcessStandards(List<DataStandard> dataStandards, object content)
        {
            object tmpData = content; //当前数据
            foreach (var item in dataStandards)
            {
                var result = ProcessStandard(item, tmpData);
                if (result.IsSuccess)
                {
                    tmpData = result.Result;
                }
                else
                {
                    break; //中止跳出
                }
            }
        }
    }
}